/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "advanced_notification_service.h"

#include "errors.h"
#include "ans_log_wrapper.h"
#include "access_token_helper.h"
#include "notification_preferences.h"
#include "notification_analytics_util.h"
#include "badge_number_callback_data.h"
#include "advanced_notification_inline.h"
#include "notification_subscriber_manager.h"
#include "enabled_notification_callback_data.h"

#include "ipc_skeleton.h"

namespace OHOS {
namespace Notification {

constexpr int32_t BADGE_NUM_LIMIT = 0;
constexpr int32_t INVALID_BADGE_NUMBER = -1;
ffrt::mutex AdvancedNotificationService::badgeQueryMutex_;
std::map<int32_t, sptr<IBadgeQueryCallback>> AdvancedNotificationService::badgeQueryCallBack_;

ErrCode AdvancedNotificationService::SetNotificationBadgeNum(int32_t num)
{
    ANS_LOGD("called");

    sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
    if (bundleOption == nullptr) {
        ANS_LOGD("null bundleOption");
        return ERR_ANS_INVALID_BUNDLE;
    }

    if (notificationSvrQueue_ == nullptr) {
        ANS_LOGE("null notificationSvrQueue");
        return ERR_ANS_INVALID_PARAM;
    }
    ErrCode result = ERR_OK;
    ffrt::task_handle handler = notificationSvrQueue_->submit_h(
        std::bind([&]() {
            ANS_LOGD("called");
            result = NotificationPreferences::GetInstance()->SetTotalBadgeNums(bundleOption, num);
        }));
    notificationSvrQueue_->wait(handler);
    return result;
}

ErrCode AdvancedNotificationService::SetShowBadgeEnabledForBundles(
    const std::map<sptr<NotificationBundleOption>, bool> &bundleOptions)
{
    ANS_LOGD("SetShowBadgeEnabledForBundles call");
    HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_14, EventBranchId::BRANCH_0);
    if (bundleOptions.empty()) {
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_INVALID_BUNDLE));
        return ERR_ANS_INVALID_BUNDLE;
    }

    bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
    if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
        ANS_LOGE("IsSystemApp is false.");
        message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).BranchId(BRANCH_1);
        NotificationAnalyticsUtil::ReportModifyEvent(message);
        return ERR_ANS_NON_SYSTEM_APP;
    }

    if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
        ANS_LOGE("Permission Denied.");
        message.ErrorCode(ERR_ANS_PERMISSION_DENIED).BranchId(BRANCH_2);
        NotificationAnalyticsUtil::ReportModifyEvent(message);
        return ERR_ANS_PERMISSION_DENIED;
    }

    if (notificationSvrQueue_ == nullptr) {
        ANS_LOGE("null notificationSvrQueue");
        message.Message("Serial queue is invalid.");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_INVALID_PARAM).BranchId(BRANCH_3));
        return ERR_ANS_INVALID_PARAM;
    }
    ErrCode result = ERR_OK;
    ffrt::task_handle handler = notificationSvrQueue_->submit_h(
        std::bind([&]() {
            for (const auto &bundleOption : bundleOptions) {
                sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption.first);
                if (bundle == nullptr) {
                    continue;
                }
                result = NotificationPreferences::GetInstance()->SetShowBadge(bundle, bundleOption.second);
                if (result == ERR_OK) {
                    HandleBadgeEnabledChanged(bundle, bundleOption.second);
                } else {
                    message.Message(bundle->GetBundleName() + "_" + std::to_string(bundle->GetUid()) +
                        "_" + std::to_string(bundleOption.second) + "set showbadge failed.");
                    NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(result).BranchId(BRANCH_4));
                }
            }
        }));
    notificationSvrQueue_->wait(handler);
    message.ErrorCode(result).Message("SetShowBadgeEnabledForBundles end").BranchId(BRANCH_5);
    NotificationAnalyticsUtil::ReportModifyEvent(message);
    ANS_LOGD("SetShowBadgeEnabledForBundles end");
    return ERR_OK;
}

ErrCode AdvancedNotificationService::SetShowBadgeEnabledForBundle(
    const sptr<NotificationBundleOption> &bundleOption, bool enabled)
{
    HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_13, EventBranchId::BRANCH_0);
    if (bundleOption == nullptr) {
        ANS_LOGE("null bundleOption");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_INVALID_BUNDLE));
        return ERR_ANS_INVALID_BUNDLE;
    }

    message.Message(bundleOption->GetBundleName() + "_" + std::to_string(bundleOption->GetUid()) +
        " en" + std::to_string(enabled));

    bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
    if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
        ANS_LOGE("IsSystemApp is false.");
        message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).BranchId(BRANCH_1);
        NotificationAnalyticsUtil::ReportModifyEvent(message);
        return ERR_ANS_NON_SYSTEM_APP;
    }

    if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
        ANS_LOGE("Permission Denied.");
        message.ErrorCode(ERR_ANS_PERMISSION_DENIED).BranchId(BRANCH_2);
        NotificationAnalyticsUtil::ReportModifyEvent(message);
        return ERR_ANS_PERMISSION_DENIED;
    }

    sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
    if (bundle == nullptr) {
        ANS_LOGE("null bundle");
        return ERR_ANS_INVALID_BUNDLE;
    }

    if (notificationSvrQueue_ == nullptr) {
        ANS_LOGE("null notificationSvrQueue");
        return ERR_ANS_INVALID_PARAM;
    }
    ErrCode result = ERR_OK;
    ffrt::task_handle handler = notificationSvrQueue_->submit_h(
        std::bind([&]() {
            ANS_LOGD("called");
            result = NotificationPreferences::GetInstance()->SetShowBadge(bundle, enabled);
            if (result == ERR_OK) {
                HandleBadgeEnabledChanged(bundle, enabled);
            }
        }));
    notificationSvrQueue_->wait(handler);
    ANS_LOGI("%{public}s_%{public}d, enabled: %{public}s, Set show badge enabled for bundle result: %{public}d",
        bundleOption->GetBundleName().c_str(), bundleOption->GetUid(), std::to_string(enabled).c_str(), result);
    message.ErrorCode(result).BranchId(BRANCH_3);
    NotificationAnalyticsUtil::ReportModifyEvent(message);
    return result;
}

void AdvancedNotificationService::HandleBadgeEnabledChanged(
    const sptr<NotificationBundleOption> &bundleOption, bool enabled)
{
    sptr<EnabledNotificationCallbackData> enabledData = new (std::nothrow)
        EnabledNotificationCallbackData(bundleOption->GetBundleName(), bundleOption->GetUid(), enabled);
    if (enabledData == nullptr) {
        ANS_LOGE("null enabledData");
        return;
    }

    NotificationSubscriberManager::GetInstance()->NotifyBadgeEnabledChanged(enabledData);
}

ErrCode AdvancedNotificationService::GetShowBadgeEnabledForBundle(const sptr<NotificationBundleOption> &bundleOption,
    const sptr<IAnsResultDataSynchronizer> &synchronizer)
{
    ANS_LOGD("called");
    if (synchronizer == nullptr) {
        ANS_LOGE("synchronizer is null");
        return ERR_ANS_INVALID_PARAM;
    }
    bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
    if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
        ANS_LOGD("VerifyNativeToken is bogus.");
        return ERR_ANS_NON_SYSTEM_APP;
    }

    if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
        return ERR_ANS_PERMISSION_DENIED;
    }

    sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
    if (bundle == nullptr) {
        ANS_LOGE("null bundle");
        return ERR_ANS_INVALID_BUNDLE;
    }

    if (notificationSvrQueue_ == nullptr) {
        ANS_LOGE("null notificationSvrQueue");
        return ERR_ANS_INVALID_PARAM;
    }
    ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([=]() {
        ANS_LOGD("called");
        ErrCode result = ERR_OK;
        bool enabled = false;
        result = NotificationPreferences::GetInstance()->IsShowBadge(bundle, enabled);
        if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
            result = ERR_OK;
            enabled = true;
        }
        synchronizer->TransferResultData(result, enabled);
    }));
    return ERR_OK;
}

ErrCode AdvancedNotificationService::GetShowBadgeEnabledForBundle(
    const sptr<NotificationBundleOption> &bundleOption, bool &enabled)
{
    ANS_LOGD("called");
    bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
    if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
        ANS_LOGD("VerifyNativeToken is bogus.");
        return ERR_ANS_NON_SYSTEM_APP;
    }
    if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
        return ERR_ANS_PERMISSION_DENIED;
    }
    sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
    if (bundle == nullptr) {
        ANS_LOGE("null bundle");
        return ERR_ANS_INVALID_BUNDLE;
    }
    if (notificationSvrQueue_ == nullptr) {
        ANS_LOGE("null notificationSvrQueue");
        return ERR_ANS_INVALID_PARAM;
    }
    ErrCode result = ERR_OK;
    ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
        ANS_LOGD("called");
        result = NotificationPreferences::GetInstance()->IsShowBadge(bundle, enabled);
        if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
            result = ERR_OK;
            enabled = true;
        }
    }));
    notificationSvrQueue_->wait(handler);
    return result;
}

ErrCode AdvancedNotificationService::GetShowBadgeEnabledForBundles(
    const std::vector<sptr<NotificationBundleOption>> &bundleOptions,
    std::map<sptr<NotificationBundleOption>, bool> &bundleEnable)
{
    ANS_LOGD("GetShowBadgeEnabledForBundles called");
    HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_16, EventBranchId::BRANCH_0);
    bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
    if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
        ANS_LOGE("IsSystemApp is false.");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_NON_SYSTEM_APP));
        return ERR_ANS_NON_SYSTEM_APP;
    }
    if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
        ANS_LOGE("Permission Denied");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_PERMISSION_DENIED).BranchId(BRANCH_1));
        return ERR_ANS_PERMISSION_DENIED;
    }
    if (notificationSvrQueue_ == nullptr) {
        ANS_LOGE("null notificationSvrQueue");
        message.Message("Serial queue is invalid.");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_INVALID_PARAM).BranchId(BRANCH_2));
        return ERR_ANS_INVALID_PARAM;
    }

    ErrCode result = ERR_OK;
    ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
        for (sptr<NotificationBundleOption> bundleOption : bundleOptions) {
            sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
            if (bundle == nullptr) {
                continue;
            }
            bool enable = false;
            result = NotificationPreferences::GetInstance()->IsShowBadge(bundle, enable);
            if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
                result = ERR_OK;
                enable = true;
            }
            if (result != ERR_OK) {
                ANS_LOGE("%{public}s_%{public}d, get showbadge failed.",
                    bundle->GetBundleName().c_str(), bundle->GetUid());
                message.Message(bundle->GetBundleName() + "_" + std::to_string(bundle->GetUid()) +
                    " get showbadge failed.");
                NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(result).BranchId(BRANCH_3));
                continue;
            }
            bundleEnable.insert(std::make_pair(bundleOption, enable));
        }
    }));
    notificationSvrQueue_->wait(handler);
    message.ErrorCode(result).Message("GetShowBadgeEnabledForBundles end").BranchId(BRANCH_4);
    NotificationAnalyticsUtil::ReportModifyEvent(message);
    ANS_LOGD("GetShowBadgeEnabledForBundles end");
    return ERR_OK;
}

ErrCode AdvancedNotificationService::GetShowBadgeEnabled(const sptr<IAnsResultDataSynchronizer> &synchronizer)
{
    ANS_LOGD("called");
    if (synchronizer == nullptr) {
        ANS_LOGE("synchronizer is null");
        return ERR_ANS_INVALID_PARAM;
    }
    sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
    if (bundleOption == nullptr) {
        return ERR_ANS_INVALID_BUNDLE;
    }

    if (notificationSvrQueue_ == nullptr) {
        ANS_LOGE("null notificationSvrQueue");
        return ERR_ANS_INVALID_PARAM;
    }
    ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([=]() {
        ANS_LOGD("called");
        ErrCode result = ERR_OK;
        bool enabled = false;
        result = NotificationPreferences::GetInstance()->IsShowBadge(bundleOption, enabled);
        if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
            result = ERR_OK;
            enabled = true;
        }
        synchronizer->TransferResultData(result, enabled);
    }));
    return ERR_OK;
}

ErrCode AdvancedNotificationService::GetShowBadgeEnabled(bool &enabled)
{
    ANS_LOGD("called");
    sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
    if (bundleOption == nullptr) {
        return ERR_ANS_INVALID_BUNDLE;
    }

    if (notificationSvrQueue_ == nullptr) {
        ANS_LOGE("null notificationSvrQueue");
        return ERR_ANS_INVALID_PARAM;
    }
    ErrCode result = ERR_OK;
    ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
        ANS_LOGD("called");
        result = NotificationPreferences::GetInstance()->IsShowBadge(bundleOption, enabled);
        if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
            result = ERR_OK;
            enabled = true;
        }
    }));
    notificationSvrQueue_->wait(handler);
    return result;
}

ErrCode AdvancedNotificationService::SetBadgeNumber(int32_t badgeNumber, const std::string &instanceKey)
{
    ANS_LOGD("called");
    if (notificationSvrQueue_ == nullptr) {
        ANS_LOGE("null notificationSvrQueue");
        return ERR_ANS_INVALID_PARAM;
    }
    int32_t callingUid = IPCSkeleton::GetCallingUid();
    std::string bundleName = GetClientBundleName();
    ANS_LOGD("SetBadgeNumber receive instanceKey:%{public}s", instanceKey.c_str());
    sptr<BadgeNumberCallbackData> badgeData = new (std::nothrow) BadgeNumberCallbackData(
        bundleName, instanceKey, callingUid, badgeNumber);
    if (badgeData == nullptr) {
        ANS_LOGE("Null badgeData.");
        return ERR_ANS_NO_MEMORY;
    }

    ffrt::task_handle handler = notificationSvrQueue_->submit_h([badgeData]() {
        ANS_LOGD("called");
        NotificationSubscriberManager::GetInstance()->SetBadgeNumber(badgeData);
    });

    return ERR_OK;
}

ErrCode AdvancedNotificationService::SetBadgeNumberForDhByBundle(
    const sptr<NotificationBundleOption> &bundleOption, int32_t badgeNumber)
{
    if (bundleOption == nullptr) {
        ANS_LOGE("null bundleOption");
        return ERR_ANS_INVALID_PARAM;
    }
    if (bundleOption->GetBundleName().empty()) {
        ANS_LOGE("SetBadgeNumberForDhByBundle Invalid bundle name.");
        return ERR_ANS_INVALID_PARAM;
    }
    if (bundleOption->GetUid() <= DEFAULT_UID) {
        ANS_LOGE("SetBadgeNumberForDhByBundle invalid uid");
        return ERR_ANS_INVALID_PARAM;
    }
    if (badgeNumber < BADGE_NUM_LIMIT) {
        ANS_LOGE("SetBadgeNumberForDhByBundle invalid badgeNumber");
        return ERR_ANS_INVALID_PARAM;
    }
    ANS_LOGI("SetBadgeNumberForDhByBundle bundleName = %{public}s uid = %{public}d",
        bundleOption->GetBundleName().c_str(), bundleOption->GetUid());
    HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_7, EventBranchId::BRANCH_6);
    message.Message(bundleOption->GetBundleName() + "_" +std::to_string(bundleOption->GetUid()) +
        " badgeNumber: " + std::to_string(badgeNumber));

    bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
    if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
        message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).Append(" Not system app.");
        NotificationAnalyticsUtil::ReportModifyEvent(message);
        ANS_LOGE("Not system app.");
        return ERR_ANS_NON_SYSTEM_APP;
    }

    if (notificationSvrQueue_ == nullptr) {
        return ERR_ANS_INVALID_PARAM;
    }

    sptr<BadgeNumberCallbackData> badgeData = new (std::nothrow) BadgeNumberCallbackData(
            bundleOption->GetBundleName(), bundleOption->GetUid(), badgeNumber);
    if (badgeData == nullptr) {
        ANS_LOGE("Null badgeData.");
        return ERR_ANS_NO_MEMORY;
    }

    ffrt::task_handle handler = notificationSvrQueue_->submit_h([badgeData]() {
        ANS_LOGD("called");
        NotificationSubscriberManager::GetInstance()->SetBadgeNumber(badgeData);
    });

    return ERR_OK;
}

ErrCode AdvancedNotificationService::SetBadgeNumberByBundle(
    const sptr<NotificationBundleOption> &bundleOption, int32_t badgeNumber)
{
    if (bundleOption == nullptr || bundleOption->GetBundleName().empty()) {
        return ERR_ANS_INVALID_PARAM;
    }
    HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_7, EventBranchId::BRANCH_6);
    message.Message(bundleOption->GetBundleName() + "_" +std::to_string(bundleOption->GetUid()) +
        " badgeNumber: " + std::to_string(badgeNumber));

    bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
    if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
        message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).Append(" Not system app.");
        NotificationAnalyticsUtil::ReportModifyEvent(message);
        ANS_LOGE("Not system app.");
        return ERR_ANS_NON_SYSTEM_APP;
    }

    sptr<NotificationBundleOption> bundle = bundleOption;
    ErrCode result = CheckBundleOptionValid(bundle);
    if (result != ERR_OK) {
        ANS_LOGE("Bundle is invalid.");
        return result;
    }

    if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER)) {
        std::string bundleName = GetClientBundleName();
        if (bundleName.empty()) {
            ANS_LOGE("Failed to get client bundle name.");
            return result;
        }
        bool isAgent = false;
        isAgent = IsAgentRelationship(bundleName, bundle->GetBundleName());
        if (!isAgent) {
            message.ErrorCode(ERR_ANS_NO_AGENT_SETTING).Append(" No agent setting.");
            NotificationAnalyticsUtil::ReportModifyEvent(message);
            ANS_LOGE("No agent setting.");
            return ERR_ANS_NO_AGENT_SETTING;
        }
    }

    if (notificationSvrQueue_ == nullptr) {
        return ERR_ANS_INVALID_PARAM;
    }

    sptr<BadgeNumberCallbackData> badgeData = new (std::nothrow) BadgeNumberCallbackData(
            bundle->GetBundleName(), bundle->GetUid(), badgeNumber);
    if (badgeData == nullptr) {
        ANS_LOGE("Null badgeData.");
        return ERR_ANS_NO_MEMORY;
    }

    ffrt::task_handle handler = notificationSvrQueue_->submit_h([badgeData]() {
        ANS_LOGD("called");
        NotificationSubscriberManager::GetInstance()->SetBadgeNumber(badgeData);
    });

    return ERR_OK;
}

ErrCode AdvancedNotificationService::GetBadgeNumber(int32_t &badgeNumber)
{
    HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_29, EventBranchId::BRANCH_0);
    sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
    if (bundleOption == nullptr) {
        message.Message("null bundleOption");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_INVALID_PARAM));
        return ERR_ANS_INVALID_BUNDLE;
    }

    if (notificationSvrQueue_ == nullptr) {
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_INVALID_PARAM).BranchId(BRANCH_1));
        return ERR_ANS_INVALID_PARAM;
    }

    int32_t userId = SUBSCRIBE_USER_INIT;
    OsAccountManagerHelper::GetInstance().GetCurrentCallingUserId(userId);
    ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
        sptr<IBadgeQueryCallback> callback = nullptr;
        badgeNumber = INVALID_BADGE_NUMBER;
        {
            std::lock_guard<ffrt::mutex> lock(badgeQueryMutex_);
            if (badgeQueryCallBack_.find(userId) == badgeQueryCallBack_.end()) {
                ANS_LOGW("BadgeQueryCallback unregistered");
                message.Message(bundleOption->GetBundleName() + "_" + std::to_string(bundleOption->GetUid()) +
                    " get badgenumber failed, badgeQueryCallback unregistered.");
                NotificationAnalyticsUtil::ReportModifyEvent(message.BranchId(BRANCH_2));
                return;
            }
            callback = badgeQueryCallBack_[userId];
        }
        if (callback == nullptr) {
            NotificationAnalyticsUtil::ReportModifyEvent(message.BranchId(BRANCH_3));
            return;
        }
        ErrCode ret = callback->OnBadgeNumberQuery(bundleOption, badgeNumber);
        if (ret != ERR_OK) {
            ANS_LOGE("OnBadgeNumberQuery bundle:%{public}s uid:%{public}d failed, ret:%{public}d, number:%{public}d",
                bundleOption->GetBundleName().c_str(), bundleOption->GetUid(), ret, badgeNumber);
            message.Message(bundleOption->GetBundleName() + "_" + std::to_string(bundleOption->GetUid()) + "_" +
                std::to_string(badgeNumber) + " get badgenumber failed.");
            NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ret).BranchId(BRANCH_4));
        }
    }));
    notificationSvrQueue_->wait(handler);
    message.Message(bundleOption->GetBundleName() + "_" + std::to_string(bundleOption->GetUid()) +
        " get badgenumber " + std::to_string(badgeNumber));
    NotificationAnalyticsUtil::ReportModifyEvent(message.BranchId(BRANCH_5));
    ANS_LOGD("Bundle(%{public}s_%{public}d) get badgenumber %{public}d", bundleOption->GetBundleName().c_str(),
        bundleOption->GetUid(), badgeNumber);
    return badgeNumber < BADGE_NUM_LIMIT ? ERR_ANS_TASK_ERR : ERR_OK;
}

ErrCode AdvancedNotificationService::RegisterBadgeQueryCallback(const sptr<IBadgeQueryCallback> &badgeQueryCallback)
{
    ANS_LOGD("RegisterBadgeQueryCallback");
    HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_29, EventBranchId::BRANCH_6);
    bool isSubSystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
    if (!isSubSystem && !AccessTokenHelper::IsSystemApp()) {
        ANS_LOGE("Not system app or SA.");
        message.Message("Not systemApp or SA.");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_NON_SYSTEM_APP));
        return ERR_ANS_NON_SYSTEM_APP;
    }

    if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
        ANS_LOGE("Permission denied.");
        message.Message("Permission denied.");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_PERMISSION_DENIED).BranchId(BRANCH_7));
        return ERR_ANS_PERMISSION_DENIED;
    }

    if (badgeQueryCallback == nullptr) {
        ANS_LOGE("badgeQueryCallback is null.");
        message.Message("badgeQueryCallback is null.");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_INVALID_PARAM).BranchId(BRANCH_8));
        return ERR_ANS_INVALID_PARAM;
    }

    int32_t userId = SUBSCRIBE_USER_INIT;
    OsAccountManagerHelper::GetInstance().GetCurrentCallingUserId(userId);
    sptr<IBadgeQueryCallback> callBack = iface_cast<IBadgeQueryCallback>(badgeQueryCallback->AsObject());
    if (callBack == nullptr) {
        ANS_LOGE("callBack is null");
        return ERR_ANS_INVALID_PARAM;
    }
    {
        std::lock_guard<ffrt::mutex> lock(badgeQueryMutex_);
        badgeQueryCallBack_.insert_or_assign(userId, callBack);
    }
    message.Message(std::to_string(userId) + " register badgequerycallback succ.");
    NotificationAnalyticsUtil::ReportModifyEvent(message.BranchId(BRANCH_9));
    ANS_LOGI("UserId(%{public}d) registerBadgeQueryCallback end", userId);
    return ERR_OK;
}

ErrCode AdvancedNotificationService::UnRegisterBadgeQueryCallback()
{
    ANS_LOGD("UnRegisterBadgeQueryCallback");
    HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_29, EventBranchId::BRANCH_10);
    bool isSubSystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
    if (!isSubSystem && !AccessTokenHelper::IsSystemApp()) {
        ANS_LOGE("Not system app or SA.");
        message.Message("Not systemApp or SA.");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_NON_SYSTEM_APP));
        return ERR_ANS_NON_SYSTEM_APP;
    }

    if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
        ANS_LOGE("Permission denied.");
        message.Message("Permission denied.");
        NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_PERMISSION_DENIED).BranchId(BRANCH_11));
        return ERR_ANS_PERMISSION_DENIED;
    }

    int32_t userId = SUBSCRIBE_USER_INIT;
    OsAccountManagerHelper::GetInstance().GetCurrentCallingUserId(userId);
    {
        std::lock_guard<ffrt::mutex> lock(badgeQueryMutex_);
        badgeQueryCallBack_.erase(userId);
    }
    message.Message(std::to_string(userId) + " unregister badgequerycallback succ.");
    NotificationAnalyticsUtil::ReportModifyEvent(message.BranchId(BRANCH_12));
    ANS_LOGI("UserId(%{public}d) unRegisterBadgeQueryCallback end", userId);
    return ERR_OK;
}
} // Notification
} // OHOS
